package com.apache.license.validator;

/**
 * 利用TEA算法对文章进行加密，解密.
 */
public class TeaUtil {
	private final static int[] KEY = new int[] { 0x789f5645, 0xf68bd5a4, 0x81963ffa, 0x458fac58 };

	/**
	 * 对内容字节数组进行加密
	 * 
	 * @param content 内容字节数组
	 * @param offset  偏移位
	 * @param key     加密解密所用的KEY数组
	 * @param times   加密轮数
	 * @return        返回加密后的字节数组
	 */
	private static byte[] encrypt(byte[] content, int offset, int[] key, int times) {//times为加密轮数
		int[] tempInt = byteToInt(content, offset);
		int y = tempInt[0], z = tempInt[1], sum = 0, i;
		int delta = 0x9e3779b9; //这是算法标准给的值
		int a = key[0], b = key[1], c = key[2], d = key[3];
		for (i = 0; i < times; i++) {
			sum += delta;
			y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
			z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
		}
		tempInt[0] = y;
		tempInt[1] = z;
		return intToByte(tempInt, 0);
	}

	/**
	 * 对加密内容字节数组进行解密
	 * 
	 * @param  encryptContent 加密的内容字节数组
	 * @param  offset         偏移位
	 * @param  key            加密解密所用的KEY数组
	 * @param  times          加密轮数
	 * @return                返回解密后的字节数组
	 */
	private static byte[] decrypt(byte[] encryptContent, int offset, int[] key, int times) {
		int[] tempInt = byteToInt(encryptContent, offset);
		int y = tempInt[0], z = tempInt[1], sum = 0, i;
		int delta = 0x9e3779b9; //这是算法标准给的值
		int a = key[0], b = key[1], c = key[2], d = key[3];
		if (times == 32)
			sum = 0xC6EF3720; /**//* delta << 5*/
		else if (times == 16)
			sum = 0xE3779B90; /**//* delta << 4*/
		else
			sum = delta * times;

		for (i = 0; i < times; i++) {
			z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
			y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
			sum -= delta;
		}
		tempInt[0] = y;
		tempInt[1] = z;

		return intToByte(tempInt, 0);
	}

	/**
	 * 字节数组转换成整形数组
	 * 
	 * @param  content 内容字节数组
	 * @param  offset  偏移位
	 * @return         返回整形数组
	 */
	private static int[] byteToInt(byte[] content, int offset) {

		int[] result = new int[content.length >> 2];//除以2的n次方 == 右移n位 即 content.length / 4 == content.length >> 2
		for (int i = 0, j = offset; j < content.length; i++, j += 4) {
			result[i] = transform(content[j + 3]) | transform(content[j + 2]) << 8 | transform(content[j + 1]) << 16
					| (int) content[j] << 24;
		}
		return result;

	}

	/**
	 * 整形数组转化成字节数组
	 * 
	 * @param  content 内容整形数组
	 * @param  offset  偏移位
	 * @return         返回字节数组
	 */
	private static byte[] intToByte(int[] content, int offset) {
		byte[] result = new byte[content.length << 2];//乘以2的n次方 == 左移n位 即 content.length * 4 == content.length << 2
		for (int i = 0, j = offset; j < result.length; i++, j += 4) {
			result[j + 3] = (byte) (content[i] & 0xff);
			result[j + 2] = (byte) ((content[i] >> 8) & 0xff);
			result[j + 1] = (byte) ((content[i] >> 16) & 0xff);
			result[j] = (byte) ((content[i] >> 24) & 0xff);
		}
		return result;
	}

	/**
	 * 字节为负数则需将其转成无符号正数
	 * 
	 * @param  temp 某字节
	 * @return      返回无符号正数
	 */
	private static int transform(byte temp) {
		int tempInt = (int) temp;
		if (tempInt < 0) {
			tempInt += 256;
		}
		return tempInt;
	}

	/**
	 * 对某字符串进行加密
	 * 
	 * @param  info  某字符串
	 * @return       返回加密后的字节数组
	 */
	private static byte[] encryptByTeaToByte(String info) {
		byte[] temp = info.getBytes();
		int n = 8 - temp.length % 8;//若temp的位数不足8的倍数,需要填充的位数
		byte[] encryptStr = new byte[temp.length + n];
		encryptStr[0] = (byte) n;
		System.arraycopy(temp, 0, encryptStr, n, temp.length);
		byte[] result = new byte[encryptStr.length];
		for (int offset = 0; offset < result.length; offset += 8) {
			byte[] tempEncrpt = encrypt(encryptStr, offset, KEY, 32);
			System.arraycopy(tempEncrpt, 0, result, offset, 8);
		}

		return result;
	}

	/**
	 * 对加密的字节数组进行解密成字符串
	 * 
	 * @param  secretInfo 加密的字节数组
	 * @return            返回解密后的字符串
	 */
	private static String decryptByTea(byte[] secretInfo) {
		byte[] decryptStr = null;
		byte[] tempDecrypt = new byte[secretInfo.length];
		for (int offset = 0; offset < secretInfo.length; offset += 8) {
			decryptStr = decrypt(secretInfo, offset, KEY, 32);
			System.arraycopy(decryptStr, 0, tempDecrypt, offset, 8);
		}

		int n = tempDecrypt[0];
		return new String(tempDecrypt, n, decryptStr.length - n);

	}

	/**
	  * 把16进制字符串转换成字节数组
	  * 
	  * @param hex 某字符串
	  * @return    返回字节数组
	  */
	private static byte[] hexStringToByte(String hex) {
		int len = (hex.length() / 2);
		byte[] result = new byte[len];
		char[] achar = hex.toCharArray();
		for (int i = 0; i < len; i++) {
			int pos = i * 2;
			result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
		}
		return result;
	}

	/**
	 * 将字符转换成字节
	 * 
	 * @param  c 字符
	 * @return   返回字符转换后的字节
	 */
	private static byte toByte(char c) {
		byte b = (byte) "0123456789ABCDEF".indexOf(c);
		return b;
	}

	/**
	 * 把字节数组转换成16进制字符串
	 * 
	 * @param  bArray 字节数组
	 * @return        返回转换后的字符串
	 */
	private static String bytesToHexString(byte[] bArray) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		for (int i = 0; i < bArray.length; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}

	/**
	 * 对字符串进行加密
	 * 
	 * @param info 某字符串
	 * @return     返回加密后的字符串
	 */
	public static String encryptByTea(String info) {
		if (!isNull(info)) {
			byte[] encryptByte = encryptByTeaToByte(info);
			info = bytesToHexString(encryptByte);
			return info;
		}
		return null;
	}

	/**
	 * 对加密的字符串进行解密
	 * 
	 * @param  encryptByte 加密后的字符串
	 * @return             返回解密后的字符串
	 */
	public static String decryptByTea(String encryptByte) {
		try {
			if (!isNull(encryptByte)) {
				byte[] byteEncypt = hexStringToByte(encryptByte);
				return decryptByTea(byteEncypt);
			}
		} catch (Exception e) {
			e.printStackTrace();
			//e.printStackTrace();
			return encryptByte;
		}
		return null;
	}

	private static boolean isNull(String text) {
		if ("".equals(text) || "null".equalsIgnoreCase(text) || null == text)
			return true;
		else
			return false;
	}

}